/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uit.ieproject.utilites;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JTextPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.DefaultCaret;
import uit.ieproject.business.ActivityBLO;
import uit.ieproject.business.GroupRegexBLO;
import uit.ieproject.business.PersonBLO;
import uit.ieproject.business.RegexBLO;
import uit.ieproject.entities.Activity;
import uit.ieproject.entities.Person;
import uit.ieproject.entities.Regex;

/**
 *
 * @author Maivia
 */
public class ExtractionThread implements Runnable {

    private PersonBLO personBLO = new PersonBLO();
    private ActivityBLO activityBLO = new ActivityBLO();
    private RegexBLO regexBLO = new RegexBLO();
    private JProgressBar pbStatus;
    private JTextPane tpStatus;
    private DefaultTableModel personListModel;
    private DefaultListModel fileListModel;
    private JButton extractFileButton;
    private JButton viewFileButton;
    private JButton deleteFileButton;
    private JButton addFileButton;
    private Map<String, String> activityMap = new HashMap<>();
    private boolean isIgnore;
    private boolean isOverwrite;
    private ArrayList<Regex> birthdayRegexs;
    private ArrayList<Regex> deathRegexs;
    private ArrayList<Regex> nicknameRegexs;
    private ArrayList<Regex> realnameRegexs;
    private ArrayList<Regex> hometownRegexs;
    private ArrayList<Regex> fatherRegexs;
    private ArrayList<Regex> motherRegexs;
    private ArrayList<Regex> activityRegexs;
    
    private JLabel lbExtractImg;
    private JLabel lbExtractName;
    private final int IMG_WIDTH;
    private final int IMG_HEIGHT;
    

    public ExtractionThread(JProgressBar pbStatus, JTextPane tpStatus,
            DefaultTableModel personListModel, JButton extractButton, JButton addFileButton,
            JButton viewFileButton, JButton deleteFileButton, DefaultListModel fileListModel,
            JLabel lbExtractImg , JLabel lbExtractName) {
        this.pbStatus = pbStatus;
        this.personListModel = personListModel;
        this.tpStatus = tpStatus;
        this.extractFileButton = extractButton;
        this.viewFileButton = viewFileButton;
        this.deleteFileButton = deleteFileButton;
        this.addFileButton = addFileButton;
        this.fileListModel = fileListModel;
        this.lbExtractImg = lbExtractImg;
        this.lbExtractName = lbExtractName;
        
        IMG_WIDTH = lbExtractImg.getWidth();
        IMG_HEIGHT = lbExtractImg.getHeight();

        DefaultCaret caret = (DefaultCaret) tpStatus.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

        isIgnore = false;
        isOverwrite = false;

        try {
            nicknameRegexs = regexBLO.getRegex(Info.NICKNAME_REGEX, Info.EXTRACT_TYPE, 1);
            realnameRegexs = regexBLO.getRegex(Info.REALNAME_REGEX, Info.EXTRACT_TYPE, 1);
            hometownRegexs = regexBLO.getRegex(Info.HOMETOWN_REGEX, Info.EXTRACT_TYPE, 1);
            fatherRegexs = regexBLO.getRegex(Info.FATHER_REGEX, Info.EXTRACT_TYPE, 1);
            motherRegexs = regexBLO.getRegex(Info.MOTHER_REGEX, Info.EXTRACT_TYPE, 1);
            birthdayRegexs = regexBLO.getRegex(Info.NAME_REGEX, Info.EXTRACT_TYPE, 1);
            deathRegexs = regexBLO.getRegex(Info.DEATH_REGEX, Info.EXTRACT_TYPE, 1);
            activityRegexs = regexBLO.getRegex(Info.ACTIVITY_REGEX, Info.EXTRACT_TYPE, 1);
        } catch (SQLException ex) {
        }
    }

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        String name;
        String birthday = Info.NOT_MATCH_INFO;
        String died = Info.NOT_MATCH_INFO;
        String nickname = Info.NOT_MATCH_INFO;
        String realname = Info.NOT_MATCH_INFO;
        String father = Info.NOT_MATCH_INFO;
        String hometown = Info.NOT_MATCH_INFO;
        String mother = Info.NOT_MATCH_INFO;

        //set status Button false when extracting:       
        extractFileButton.setEnabled(false);
        addFileButton.setEnabled(false);
        viewFileButton.setEnabled(false);
        deleteFileButton.setEnabled(false);

        TextpaneUtil.setTextPane(tpStatus, "-------BẮT ĐẦU RÚT TRÍCH!-------\n", Color.black);

        //Read file:
        try {
            String content;
            float floatValuePBar = 0;
            int numFiles = fileListModel.size();
            float increase = (float) 100 / numFiles;
            read_file_loop:
            for (int i = numFiles - 1; i >= 0; i--) {
                //increase progess bar value
                floatValuePBar += increase;
                pbStatus.setValue(Math.round(floatValuePBar));

                File file = (File) fileListModel.get(i);
                ArrayList<String> contentFile = FileUtil.senTokenize(file);
                content = contentFile.get(0);
                name = contentFile.get(1);

                //delete extract file:
                fileListModel.removeElementAt(i);

                TextpaneUtil.setTextPane(tpStatus, "Tập tin ", Color.black);
                TextpaneUtil.setTextPane(tpStatus, file.getName(), Color.blue);
                TextpaneUtil.setTextPane(tpStatus, " đang được phân tích!\n", Color.black);

                if (!name.isEmpty()) {
                    int check = personBLO.checkPersonExists(name);

                    //Handle if name is existed:
                    if (check != 0) {
                        //not overwrite all:
                        if (isIgnore == true && isOverwrite == false) {
                            showExistNameWarning(name, tpStatus, Color.black, Color.orange);
                            continue read_file_loop;
                        }
                        //overwrite all:
                        if (isIgnore == true && isOverwrite == true) {
                            TextpaneUtil.setTextPane(tpStatus, "Xóa thông tin cũ của nhân vật ", Color.black);
                            TextpaneUtil.setTextPane(tpStatus, name + "\n", Color.orange);
                            deletePerson(name, personListModel);
                        }
                        if (isIgnore == false) {
                            JCheckBox checkbox = new JCheckBox("Thực hiện với tất cả các nhân vật khác");
                            String message = "Thông tin nhân vật " + name + " đã tồn tại. Bỏ qua nhân vật này?";
                            Object[] params = {message, checkbox};
                            Object[] buttons = {"Bỏ qua", "Ghi đè"};
                            int dialogResult = JOptionPane.showOptionDialog(null, params, "Warning", JOptionPane.WARNING_MESSAGE, 0, null, buttons, buttons[1]);
                            isIgnore = checkbox.isSelected();
                            if (dialogResult == 0) {    //not overwrite
                                isOverwrite = false;
                                showExistNameWarning(name, tpStatus, Color.black, Color.orange);
                                continue read_file_loop;
                            } else {
                                isOverwrite = true;
                                deletePerson(name, personListModel);
                            }
                        }
                    }

                    //parse content:
                    String[] contentParagraph = content.split("\n");
                    if (contentParagraph.length > 0) {
                        for (int paragraph = 0; paragraph < contentParagraph.length; paragraph++) {
                            String currentContent = contentParagraph[paragraph];

                            //BIRTH 
                            if (birthday.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph == 0) {
                                    birthday = getMatchesString(birthdayRegexs, currentContent, Info.BIRTHDAY_GROUP);
                                    if (birthday.matches(".*\\d.*")) {
                                        if (!ExtractUtil.isValidBirthday(birthday)) {
                                            birthday = ExtractUtil.getCorrectBirthday(birthday);
                                        }
                                    } else {
                                        birthday = Info.NOT_MATCH_INFO;
                                    }
                                }
                            }

                            //DEATH
                            if (died.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph == 0) {
                                    died = getMatchesString(deathRegexs, currentContent, Info.DEATH_GROUP);
                                    if (died.length() < 3) {
                                        died = ExtractUtil.getCorrectDeathYear(birthday, died);
                                    }
                                }
                            }

                            //NICKNAME
                            if (nickname.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph <= 1) {
                                    nickname = getMatchesString(nicknameRegexs, currentContent, Info.NICKNAME_GROUP);
                                }
                            }

                            //REALNAME
                            if (realname.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph <= 1) {
                                    realname = getMatchesString(realnameRegexs, currentContent, Info.REALNAME_GROUP);
                                }
                            }


                            //HOMETOWN
                            if (hometown.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph <= 2) {
                                    hometown = getMatchesString(hometownRegexs, currentContent, Info.HOMETOWN_GROUP);
                                    hometown = ExtractUtil.getCorrectHometown(hometown);
                                }
                            }

                            //FATHER
                            if (father.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph <= 2) {
                                    father = getMatchesString(fatherRegexs, currentContent, Info.FATHER_GROUP);
                                }
                            }

                            //MOTHER
                            if (mother.equals(Info.NOT_MATCH_INFO)) {
                                if (paragraph <= 2) {
                                    mother = getMatchesString(motherRegexs, currentContent, Info.MOTHER_GROUP);
                                }
                            }


                            //ACTIVITY
                            if (paragraph >= 1) {
                                ArrayList<String> events = getMatchesActivityArray(
                                        activityRegexs, contentParagraph[paragraph], Info.TIME_GROUP, Info.ACT_GROUP);
                                if (events.size() > 0) {
                                    for (int index = 0; index < events.size() - 1; index += 2) {
                                        if (ExtractUtil.isValidActivity(events.get(index + 1))) {
                                            String formatedTime = ExtractUtil.formatYear(events.get(index), "-");
                                            activityMap.put(formatedTime, events.get(index + 1));
                                        }
                                    }

                                    //remove duplicated activity 
                                    for (int index = 0; index < events.size() - 1; index += 2) {
                                        for (int j = 0; j < index; j += 2) {
                                            String compareValue = activityMap.get(events.get(index));
                                            String chooseValue = activityMap.get(events.get(j));
                                            if (compareValue != null && chooseValue != null) {
                                                if (compareValue.contains(chooseValue) && !compareValue.equals(chooseValue)) {
                                                    activityMap.remove(events.get(index));
                                                } else if (chooseValue.contains(compareValue) && !compareValue.equals(chooseValue)) {
                                                    activityMap.remove(events.get(j));
                                                }
                                            }
                                            String compareTime = events.get(j);
                                            String chooseTime = events.get(index);
                                            if (compareTime != null && chooseTime != null) {
                                                if (compareTime.contains(chooseTime) && !compareTime.equals(chooseTime)) {
                                                    activityMap.remove(events.get(index));
                                                } else if (chooseTime.contains(compareTime) && !compareTime.equals(chooseTime)) {
                                                    activityMap.remove(events.get(j));
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                    }

                    Person person = new Person();
                    person.setName(name);
                    person.setBirthday(birthday);
                    person.setDied(died);
                    person.setHometown(hometown);
                    person.setNickname(nickname);
                    person.setFather(father);
                    person.setMother(mother);
                    person.setRealname(realname);
                    Long id = personBLO.addPerson(person);

                    if (!activityMap.isEmpty()) {
                        Activity activity = new Activity();
                        activity.setPersonId(id);
                        Iterator ite = activityMap.keySet().iterator();
                        while (ite.hasNext()) {
                            String t = ite.next().toString();
                            activity.setTime(t);
                            activity.setAct(activityMap.get(t));
                            activityBLO.addActivity(activity);
                        }
                    }
                    activityMap.clear();

                    TextpaneUtil.setTextPane(tpStatus, "Thông tin nhân vật ", Color.black);
                    TextpaneUtil.setTextPane(tpStatus, name, Color.orange);
                    TextpaneUtil.setTextPane(tpStatus, " đã được lưu lại!\n", Color.black);
                    TextpaneUtil.setTextPane(tpStatus, "----------------------\n", Color.black);

                    personListModel.addRow(new Object[]{TableUtil.getLastSeq(personListModel) + 1, name, id});

                    //Copy file:
                    FileUtil.saveFile(true, null,file, name, "txt");

                    //Copy image:
                    String type = "jpg";
                    File fileImage = FileUtil.getImageFromPath(name, file.getAbsolutePath(), type);
                    if ( fileImage !=null && fileImage.exists()) {
                        FileUtil.saveFile(true, null, fileImage, name, type);
                    }
                    
                    //Show Image and name:
                    ImageUtil.showImage(lbExtractImg, name, IMG_WIDTH, IMG_HEIGHT, null);
                    lbExtractName.setText(name);

                    birthday = Info.NOT_MATCH_INFO;
                    died = Info.NOT_MATCH_INFO;
                    nickname = Info.NOT_MATCH_INFO;
                    realname = Info.NOT_MATCH_INFO;
                    father = Info.NOT_MATCH_INFO;
                    hometown = Info.NOT_MATCH_INFO;
                    mother = Info.NOT_MATCH_INFO;

                } else {
                    TextpaneUtil.setTextPane(tpStatus, "Thông tin nhân vật trong tập tin ", Color.black);
                    TextpaneUtil.setTextPane(tpStatus, file.getName(), Color.red);
                    TextpaneUtil.setTextPane(tpStatus, " không xác định!\n", Color.black);
                    TextpaneUtil.setTextPane(tpStatus, "----------------------\n", Color.black);
                }
                /*try {
                 Thread.sleep(50);
                 } catch (InterruptedException e) {
                 }*/
            }

            //progress bar reach final value:
            pbStatus.setValue(100);
            //Set status button after extraction:
            addFileButton.setEnabled(true);

            TextpaneUtil.setTextPane(tpStatus, "-------RÚT TRÍCH HOÀN THÀNH!-------", Color.blue);
            long stop = System.currentTimeMillis();
            System.out.println("total: " + (stop - start));
        } catch (SQLException | IOException ex) {
        }
    }

    //Rectangle rect =
    //        tbListPersons.getCellRect(tbListPersons.getRowCount(), 0, true);
    //tbListPersons.scrollRectToVisible(rect);
    private void showExistNameWarning(String name, JTextPane textpane, Color normal, Color special) {
        TextpaneUtil.setTextPane(textpane, "Thông tin nhân vật ", normal);
        TextpaneUtil.setTextPane(textpane, name, special);
        TextpaneUtil.setTextPane(textpane, " đã tồn tại!\n", normal);
        TextpaneUtil.setTextPane(textpane, "Bỏ qua nhân vật này!\n", normal);
        TextpaneUtil.setTextPane(textpane, "----------------------\n", normal);
    }

    private void deletePerson(String name, DefaultTableModel model) {
        try {
            int row = 0;
            int numPersons = model.getRowCount();
            for (int i = 0; i < numPersons; i++) {
                String nameValue = model.getValueAt(i, 1).toString();
                if (name.equals(nameValue)) {
                    row = i;
                }
            }
            long[] id = new long[1];
            id[0] = Long.valueOf(model.getValueAt(row, 2).toString());
            if (id[0] != 0) {
                personBLO.deletePersons(id);
            }
            model.removeRow(row);
            TableUtil.resetSeq(model);
        } catch (SQLException ex) {
        }
    }

    private String getMatchesString(ArrayList<Regex> regexs, String content, String groupname) {
        String matches = Info.NOT_MATCH_INFO;
        Pattern pattern;
        Matcher matcher;
        int numRegexs = regexs.size();
        for (int i = 0; i < numRegexs; i++) {
            Regex regex = regexs.get(i);
            String expression = regex.getExpression();
            pattern = Pattern.compile(expression);
            matcher = pattern.matcher(content);
            while (matcher.find()) {
                if (matcher.group(groupname.trim()) != null && matcher.group(groupname.trim()).trim().length()!=0) {
                    matches = matcher.group(groupname.trim()).trim();
                }
            }
        }
        return matches;
    }

    private ArrayList<String> getMatchesActivityArray(ArrayList<Regex> activityRegexs, String content, String timeGroup, String actGroup) {
        ArrayList<String> map = new ArrayList<>();
        //String results = ""; // time|activity
        Pattern pattern;
        Matcher matcher;
        String time = "";
        String act = "";
        int numRegexs = activityRegexs.size();
        for (int i = 0; i < numRegexs; i++) {
            Regex regex = activityRegexs.get(i);
            String expression = regex.getExpression();
            pattern = Pattern.compile(expression);
            matcher = pattern.matcher(content);
            while (matcher.find()) {
                if (matcher.group(timeGroup).trim() != null && matcher.group(actGroup).trim() != null) {
                    time = matcher.group(timeGroup).trim();
                    act = matcher.group(actGroup).trim();
                    if (!time.equals("") && !act.equals("")) {
                        map.add(time);
                        map.add(act);
                        time = "";
                        act = "";
                    }
                }
            }
        }
        return map;
    }   
}
